使用Github Actions自动打包Go项目


前言

如果用过 Gitlab Ci, 相信对此也非常熟悉,GitHub ActionsGitHub 推出的持续集成(Continuous Integration,简称 CI)服务,它提供了整套虚拟服务器环境,基于它可以进行构建、测试、打包、部署项目等等操作

快速开始(Quickstart)

在自己的 Github 仓库中找到 Actions 标签页

点击 Configure, 此时会生成一个 .github/workflow/go.yml 文件

 1# This workflow will build a golang project
 2# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
 3
 4name: Go
 5
 6on:
 7  push:
 8    branches: [ "master" ]
 9  pull_request:
10    branches: [ "master" ]
11
12jobs:
13
14  build:
15    runs-on: ubuntu-latest
16    steps:
17      - uses: actions/checkout@v3
18        - name: Set up Go
19          uses: actions/setup-go@v3
20        with:
21          go-version: 1.19
22      - name: Build
23        run: go build -v ./...
24      - name: Test
25        run: go test -v ./...

多平台编译(Cross Compile)

交叉编译

对于非 CGO 项目,Go 提供了一种十分方便的方式来进行交叉编译,只需要指定 GOOSGOARCH 环境变量

  • Mac下编译Linux, Windows平台的64位可执行程序:

    1$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
    2$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .
  • Linux下编译Mac, Windows平台的64位可执行程序:

    1$ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build .
    2$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .

同样的,我们可以在 Gtihub Actions 中设置环境变量来编译非 CGO 项目,这里需要使用 matrix 策略,让我们基于不同的参数创建并行的任务,比如编译Go时指定不同的环境变量

  • 首先编写任务

     1jobs:
     2  build:
     3    strategy:
     4      matrix:
     5        goos: [linux, darwin]
     6        goarch: [amd64]
     7
     8    runs-on: ubuntu-latest
     9
    10    steps:
    11      - name: Checkout
    12        uses: actions/checkout@v3
    13      - name: Set up Go
    14        uses: actions/setup-go@v3
    15        with:
    16          go-version: 1.19
    17      - name: Download dependencies
    18        run: go mod download
    19      - name: Build
    20        run: go build -v -o snow .
    21        # 指定编译时的环境变量
    22        env:
    23          GOOS: ${{ matrix.goos }}
    24          GOARCH: ${{ matrix.goarch }}
    25          CGO_ENABLED: 0

    这样就创建了 GOOS=linux GOARCH=amd64GOOS=darwin GOARCH=amd64 的两个任务, 当 goarch 增加一个 arm 的参数后,会组合成四个任务, 如果需要指定或者排除某个选项,可以使用 include 或者 exclude

     1matrix:
     2  goos: [linux, darwin]
     3  goarch: [amd64, arm]
     4  # 只包括linux编译选项
     5  include:
     6    - goos: linux
     7      goarch: amd64
     8    - goos: linux
     9      goarch: arm
    10  # 排除所有关于arm的编译选项
    11  exclude:
    12    - goarch: arm
  • 然后执行 git push, 这样就能在 GithubActions 标签页看到执行结果

跨平台编译

如果是非 CGO 项目,可以使用Go内置的交叉编译,但如果是 CGO 项目,上述的交叉编译大概率会失败(相关问题:go-libsass), 所以我们需要基于不同的平台来进行编译,幸运的是,Github Actions 对此支持的非常好,

  • 编写新任务

     1jobs:
     2  build:
     3    strategy:
     4      matrix:
     5        build: [macos, linux]
     6        include:
     7          - build: macos
     8            os: macos-latest
     9          - build: linux
    10            os: ubuntu-18.04
    11    runs-on: ${{ matrix.os }}
    12    steps:
    13      - name: Checkout
    14        uses: actions/checkout@v3
    15      - name: Set up Go
    16        uses: actions/setup-go@v3
    17        with:
    18          go-version: 1.19
    19      - name: Download dependencies
    20        run: go mod download
    21      - name: Build
    22        run: go build -v -o snow .
    23        env:
    24          CGO_ENABLED: 1

    注意 runs-on 使用的 matrix.os 变量, 它允许我们分别使用 ubuntu-18.04macos-latest 两个平台进行编译,这时不用指定 GOOSGOARCH 参数

  • 执行 git push, 可以看到执行结果

发布(Release)

当编译好一个二进制文件后,需要发布到 GithubRelease 页,这时就需要添加新的任务, 目前官方的actions/create-release已经无人维护,所以此次选择另外一个ncipollo/release-action

 1name: Release
 2
 3on:
 4  # 只在预发布时才执行
 5  release:
 6    types: [prereleased]
 7
 8jobs:
 9  build:
10    strategy:
11      matrix:
12        build: [macos, linux]
13        include:
14          - build: macos
15            os: macos-latest
16            archive-name: darwin.tar.gz
17          - build: linux
18            os: ubuntu-latest
19            archive-name: linux.tar.gz
20
21    # 需要设置写权限才能自动发布
22    permissions:
23      contents: write
24
25    steps:
26      ...
27      # 把二进制文件打包成压缩文件
28      - name: Prepare Packaging
29        run: tar zcvf snow-${{ matrix.archive-name }}.tar.gz snow LICENSE
30
31      # 上传附件
32      - name: Upload Artifacts
33        uses: actions/upload-artifact@v3
34        with:
35          name: snow-${{ matrix.archive-name }}.tar.gz
36          path: snow-${{ matrix.archive-name }}.tar.gz
37
38      # 发布release版本
39      - name: Release version
40        uses: ncipollo/release-action@v1
41        if: github.event_name == 'release'
42        with:
43          allowUpdates: true
44          artifacts: snow-${{ matrix.archive-name }}.tar.gz
45          token: ${{ secrets.GITHUB_TOKEN }}

Github Actions 执行完成后,就能在 Release 页看到我们发布的 Package

FAQ

version `GLIBC_2.33' not found

使用 Github Actions 发布一个新的版本,下载到本地执行时报错

1./snow: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./snow)
2./snow: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./snow)
3./snow: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./snow)
4./snow: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by ./snow)

这是由于使用的 ubuntu 版本太高导致, 降低版本即可

1include:
2...
3-   os: ubuntu-latest
4+   os: ubuntu-18.04

Bad CPU type in executable

这是由于最新的 macos-latest 仅包括arm64,不再包括x86_64导致,如果需要使用x86_64,请指定版本 macos-13

作者: honmaple
链接: https://honmaple.me/articles/2023/03/使用Github Actions自动打包Go项目.html
版权: CC BY-NC-SA 4.0 知识共享署名-非商业性使用-相同方式共享4.0国际许可协议
wechat
alipay

加载评论